﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Runtime.InteropServices;
using System.IO;
using Lucene.Net.Documents;
using CommonSearchModule;
using Lucene.Net.Index;
using Lucene.Net.Analysis.Standard;

namespace CreateIndexFile
{
    /// <summary>
    /// 索引文件基类
    /// </summary>
    public abstract class IndexFileBase
    {
        #region Constructors
        public IndexFileBase(string documentsPath)
        {
            this.DocumentsPath = documentsPath;
            writer = new IndexWriter(this.CreateSearchIndexPath, new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29), true, IndexWriter.MaxFieldLength.UNLIMITED);
        }
        #endregion

        #region  Properies
        /// <summary>
        /// 数据库连接串1
        /// </summary>
        protected readonly string connString = ConfigurationManager.AppSettings["connString"];
        /// <summary>
        /// 数据库连接串2
        /// </summary>
        protected readonly string connString_LiveCourse = ConfigurationManager.AppSettings["connString_LiveCourse"];
        /// <summary>
        /// 数据库连接串3
        /// </summary>
        protected readonly string connString_YiWen = ConfigurationManager.AppSettings["connString_YiWen"];

        /// <summary>
        /// 索引操作对象
        /// </summary>
        protected IndexWriter writer { get; private set; }

        /// <summary>
        /// 配置文件路径
        /// </summary>
        public string ConfigPath { get { return Path.Combine(this.DocumentsPath, "Config.ini"); } }

        /// <summary>
        /// 索引文件存放总目录
        /// </summary>
        public string DocumentsPath { get; protected set; }

        /// <summary>
        /// 要生成的索引文件的目录
        /// </summary>
        public string CreateSearchIndexPath { get { return GetCreatePath(); } }
        #endregion

        #region Protected Methods
        /// <summary>
        /// 获取将要生成索引的文件目录
        /// </summary>
        /// <returns></returns>
        protected string GetCreatePath()
        {
            string createPath = "";

            string path1 = Path.Combine(DocumentsPath, "1");//文件夾１
            string path2 = Path.Combine(DocumentsPath, "2");//文件夾２

            if (!System.IO.Directory.Exists(DocumentsPath)) System.IO.Directory.CreateDirectory(DocumentsPath);

            if (File.Exists(ConfigPath))
            {
                StringBuilder sbPath = new StringBuilder(500);
                GetPrivateProfileString("Index", "Path", "", sbPath, 500, ConfigPath);

                string strPath = sbPath.ToString();
                if (strPath.IndexOf("1") != -1)
                {
                    createPath = path2;
                }
                else
                {
                    createPath = path1;
                }
            }
            else
            {
                createPath = path1;
                WritePrivateProfileString("Index", "Path", createPath, ConfigPath);
            }
            if (!System.IO.Directory.Exists(createPath)) System.IO.Directory.CreateDirectory(createPath);

            return createPath;
        }

        /// <summary>
        /// 设置生成索引文件的目录
        /// </summary>
        protected void SetCreatePath()
        {
            WritePrivateProfileString("Index", "Path", CreateSearchIndexPath, ConfigPath);
        }

        /// <summary>
        /// 初始化Document流中的字段field
        /// Field.Index 	Field.Store 	说明
        /// TOKENIZED（分词） 	YES 	被分词索引且存储
        /// TOKENIZED 	        NO 	被分词索引但不存储
        /// NO 	                YES 	这是不克不及被搜刮的，它只是被搜刮内容的从属物。如URL等
        /// UN_TOKENIZED 	    YES/NO 	不被分词，它作为一个整体被搜刮，搜一项目组是搜不出来的
        /// NO 	                NO 	没有这种用法
        /// Index选项
        ///Index.ANALYZED – 索引并分词(适用于body, title, abstract等.).
        ///Index.NOT_ANALYZED – 索引但不分词,可以使用NORM方式.(可以人为干预提权)
        ///Index.ANALYZED_NO_NORMS – 索引并分词但不使用NORM方式(不可认为提权)
        ///Index.NOT_ANALYZED_NO_NORMS – 索引但不分词也不使用NORM方式(经常用到,存储标志值最好的方式.)
        ///index.NO – 不索引
        ///Store选项
        ///Store.YES – 存储
        ///Store.NO  – 不存储
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        protected virtual Document InitDocument(Search_Entity entity)
        {
            Document doc = new Document();
            doc.Add(new Field(FieldKeys.PrimaryKey, entity.PrimaryKey.ToString(), Field.Store.YES, Field.Index.ANALYZED));
            doc.Add(new Field(FieldKeys.ID, entity.ID.ToString(), Field.Store.YES, Field.Index.ANALYZED));
            if (!string.IsNullOrEmpty(entity.Name))
                doc.Add(new Field(FieldKeys.Name, entity.Name, Field.Store.YES, Field.Index.ANALYZED));
            if (!string.IsNullOrEmpty(entity.Info))
                doc.Add(new Field(FieldKeys.Info, entity.Info, Field.Store.YES, Field.Index.ANALYZED));
            if (!string.IsNullOrEmpty(entity.CategoryName))
                doc.Add(new Field(FieldKeys.CategoryName, entity.CategoryName, Field.Store.YES, Field.Index.ANALYZED));
            if (!string.IsNullOrEmpty(entity.PropertyName))
                doc.Add(new Field(FieldKeys.PropertyName, entity.PropertyName.TrimEnd(new char[] { '|' }), Field.Store.YES, Field.Index.ANALYZED));
            if (!string.IsNullOrEmpty(entity.PackageTime))
                doc.Add(new Field(FieldKeys.PackageTime, entity.PackageTime, Field.Store.YES, Field.Index.ANALYZED));
            if (!string.IsNullOrEmpty(entity.SearchUrlType))
                doc.Add(new Field(FieldKeys.SearchUrlType, entity.SearchUrlType, Field.Store.YES, Field.Index.ANALYZED));

            //  doc.Add(new Field(FieldKeys.Price, entity.Price.ToString(), Field.Store.YES, Field.Index.ANALYZED));
            doc.Add(new NumericField(FieldKeys.Price, Field.Store.YES, true).SetDoubleValue(entity.Price));
            doc.Add(new Field(FieldKeys.SearchKey, "key", Field.Store.NO, Field.Index.ANALYZED));
            if (!string.IsNullOrEmpty(entity.ExtentionField1))
                doc.Add(new Field(FieldKeys.ExtentionField1, entity.ExtentionField1, Field.Store.YES, Field.Index.ANALYZED));
            if (!string.IsNullOrEmpty(entity.ExtentionField2))
                doc.Add(new Field(FieldKeys.ExtentionField2, entity.ExtentionField2, Field.Store.YES, Field.Index.ANALYZED));
            if (!string.IsNullOrEmpty(entity.ExtentionField3))
                doc.Add(new Field(FieldKeys.ExtentionField3, entity.ExtentionField3, Field.Store.YES, Field.Index.ANALYZED));
            if (!string.IsNullOrEmpty(entity.ExtentionField4))
                doc.Add(new Field(FieldKeys.ExtentionField4, entity.ExtentionField4, Field.Store.YES, Field.Index.ANALYZED));
            if (!string.IsNullOrEmpty(entity.ExtentionField5))
                doc.Add(new Field(FieldKeys.ExtentionField5, entity.ExtentionField5, Field.Store.YES, Field.Index.ANALYZED));
            return doc;
        }

        /// <summary>
        /// 生成具体索引的逻辑
        /// </summary>
        public abstract void Create();
        [DllImport("kernel32")]
        private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);

        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);

        //修饰符用于声明在外部实现的方法。extern 修饰符的常见用法是在使用 Interop 服务调入非托管代码时与 DllImport 属性一起使用。在这种情况下，还必须将方法声明为 static
        #endregion
    }
}
